package com.ustc.hewei.rpc.server.register.notify;

import com.ustc.hewei.rpc.client.net.SendHandler;
import com.ustc.hewei.rpc.common.Utils.MessageSerialize;
import com.ustc.hewei.rpc.common.protocol.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
* @description: 服务端给注册中心发送通知
* @author hewei
* @date 2022/8/17 19:08
* @version 1.0
*/

@Slf4j
public class NotifyRegister {
    private String registerCenterIp;

    public NotifyRegister(String registerCenterIp) {
        this.registerCenterIp = registerCenterIp;
    }

    /*
     * @description: 发送通知，在服务进行注册的时候调用
     * @param service
     * @author: hewei
     * @date: 2022/8/17 21:41
     **/
    public void sendNotify(Service service) {
        NotifyMessage notifyMessage = new NotifyMessage();
        String key = "rpc/" + service.getName() + "/service";
        notifyMessage.setService(service).setKey(key).setStatus(NotifyType.REGISTER);
        byte[] data = MessageSerialize.objectToByteArray(notifyMessage);
        byte[] resp = notifySend(data, service);
        NotifyMessage message = MessageSerialize.byteArrayToNotify(resp);
        if (message.getStatus() == NotifyType.SUCCESS) {
            log.info("服务 {}, 注册中心监控成功！", service);
        } else log.error("服务 {}, 注册中心监控失败！", service);
    }

    /*
     * @description: 将通知发送出去，并接收到注册中心的响应信息
     * @param data NotifyMessage的序列化数组
     * @param service
     * @return byte[] 从注册中心返回的响应信息
     * @author: hewei
     * @date: 2022/8/17 21:42
     **/
    public byte[] notifySend(byte[] data, Service service) {
        SendHandler sendHandler = new SendHandler(data);
        byte[] response;

        //将地址进行分割，因为形式是"ip：port"
        String[] split = registerCenterIp.split(":");
        int port = Integer.parseInt(split[1]);
        String ip = split[0];

        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            new Bootstrap().group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    //设置可以接收的大小，默认为2048个字节，不够用
                    //.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //调用自定义的消息处理器
                            socketChannel.pipeline().addLast(sendHandler);
                        }
                    }).connect(ip, port).sync();
            response = (byte[]) sendHandler.getResponse();
            log.info("服务 {}, 注册中心返回信息成功！", service);
        } catch (InterruptedException e) {
            throw new RuntimeException("客户端网络连接异常！", e);
        } finally {
            group.shutdownGracefully();
        }
        return response;
    }
}
